package com.md.util;

import lombok.experimental.UtilityClass;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * @author 刘骄阳
 * 2024-05-19 23:29
 */
@UtilityClass
public class NodeUtil {

  public static Optional<Node> findNode(final Node node, final String nodeKey) {
    return operationNodeChildren(node, it -> {
      if (Objects.equals(nodeKey, it.getLocalName())) {
        return it;
      }
      return null;
    });
  }

  public static String readNodeValue(final Node node) {
    StringBuilder content = new StringBuilder();
    judgeNodeChildren(node, it -> {
      if (it.getNodeValue() != null) {
        content.append(it.getNodeValue());
      }
      return true;
    });
    return content.toString();
  }

  /**
   * 操作子节点
   *
   * @param node     节点
   * @param runnable 要执行的操作
   * @param <T>      节点
   * @return 节点
   */
  private static <T> Optional<T> operationNodeChildren(final Node node, final Function<Node, T> runnable) {
    NodeList childNodes = node.getChildNodes();
    int nodeLength = childNodes.getLength();
    for (int i = 0; i < nodeLength; i++) {
      Optional<T> optionalResult = Optional.ofNullable(runnable.apply(childNodes.item(i)));
      if (optionalResult.isPresent()) {
        return optionalResult;
      }
      Optional<T> recursiveResult = operationNodeChildren(childNodes.item(i), runnable);
      if (recursiveResult.isPresent()) {
        return recursiveResult;
      }
    }
    return Optional.empty();
  }

  private static void judgeNodeChildren(final Node node, final Predicate<Node> runnable) {
    NodeList childNodes = node.getChildNodes();
    int nodeLength = childNodes.getLength();
    for (int i = 0; i < nodeLength; i++) {
      Node item = childNodes.item(i);
      if (runnable.test(item)) {
        judgeNodeChildren(item, runnable);
      }
    }
  }
}
